package mqtt

import (
	"strings"
	"time"

	"github.com/project-flogo/core/data/coerce"
)

// Settings settings
type Settings struct {
	Name                 string                 `md:"name"`
	Servers              []interface{}          `md:"servers,required"` // The broker URL
	ClientID             string                 `md:"clientId"`         // The id of client
	Username             string                 `md:"username"`         // The user's name
	Password             string                 `md:"password"`         // The user's password
	CleanSession         bool                   `md:"cleanSession"`     // Clean session flag
	Order                bool                   `md:"order"`
	WillEnabled          bool                   `md:"willEnabled"`
	WillTopic            string                 `md:"willTopic"`
	WillPayload          []byte                 `md:"willPayload"`
	WillQos              int                    `md:"willQos"`
	WillRetained         bool                   `md:"willRetained"`
	ProtocolVersion      int                    `md:"protocolVersion"`
	TLSConfig            map[string]interface{} `md:"tlsConfig"`
	KeepAlive            string                 `md:"keepAlive"` // Keep Alive time in seconds
	PingTimeout          string                 `md:"pingTimeout"`
	ConnectTimeout       string                 `md:"connectTimeout"`
	MaxReconnectInterval string                 `md:"maxReconnectInterval"`
	AutoReconnect        bool                   `md:"autoReconnect"` // Enable Auto-Reconnect
	Store                string                 `md:"store"`         // The store for message persistence
	WriteTimeout         string                 `md:"writeTimeout"`
	ResumeSubs           bool                   `md:"resumeSubs"`
	HTTPHeaders          map[string]string      `md:"httpHeaders"`
	// SSLConfig     map[string]interface{} `md:"sslConfig"`         // SSL Configuration
}

// Input input
type Input struct {
	Topic      string         `md:"topic"`
	Payload    []byte         `md:"payload"` // The message to send
	Qos        int            `md:"qos"`
	IsRetained bool           `md:"isRetained"`
	Timeout    *time.Duration `md:"timeout"`
}

// ToMap input to map
func (i *Input) ToMap() map[string]interface{} {
	return map[string]interface{}{
		"topic":      i.Topic,
		"payload":    i.Payload,
		"qos":        i.Qos,
		"isRetained": i.IsRetained,
		"timeout":    i.Timeout.String(),
	}
}

// FromMap input from map
func (i *Input) FromMap(values map[string]interface{}) error {
	topic, err := coerce.ToString(values["topic"])
	if err != nil {
		return err
	}
	i.Topic = topic

	payload, err := coerce.ToBytes(values["payload"])
	if err != nil {
		return err
	}
	i.Payload = payload

	qos, err := coerce.ToInt(values["qos"])
	if err != nil {
		return err
	}
	i.Qos = qos

	isRetained, err := coerce.ToBool(values["isRetained"])
	if err != nil {
		return err
	}
	i.IsRetained = isRetained

	timeoutStr, err := coerce.ToString(values["timeout"])
	if err != nil {
		return err
	}
	if strings.TrimSpace(timeoutStr) == "" {
		i.Timeout = nil
	} else {
		d, err := time.ParseDuration(timeoutStr)
		if err != nil {
			return err
		}
		i.Timeout = &d
	}
	return nil
}

// Output output
type Output struct {
	Err string `md:"err"` // The data recieved
}

// ToMap output to map
func (o *Output) ToMap() map[string]interface{} {
	return map[string]interface{}{
		"err": o.Err,
	}
}

// FromMap output from map
func (o *Output) FromMap(values map[string]interface{}) error {
	str, err := coerce.ToString(values["err"])
	if err != nil {
		return err
	}
	o.Err = str
	return nil
}
